<script setup lang="ts">
import {computed, nextTick, onMounted, ref, watch} from "vue";
import {storeToRefs} from "pinia";
import Command from "@/views/Control/components/Command.vue";
import {CommandType} from "@/interface/Command.js";
import {Add} from "@vicons/carbon";
import {VueDraggable} from "vue-draggable-plus";
import {useUserProfile} from "@/stores/useUserProfile.js";
import {generateRandomKey, hexStringToUint8Array, parseArrayBuffer} from "@/utils/byteParser.js";


const {deviceList} = storeToRefs(useUserProfile())
const {commandConfig} = useUserProfile()
const props = defineProps<{
	deviceList: any[];
	commandList: CommandType[];
}>();
const emit = defineEmits(["update:commandList"])
// 创建一个响应式的本地副本
const localCommandList = computed({
	get: () => props.commandList,
	set: (newVal) => {
		// 更新指令
		emit("update:commandList", newVal);
	}
});

watch(() => props.commandList, (newValue) => {
	localCommandList.value = newValue;
	console.log("29更新了")
}, {deep: true})

/**
 * 删除一个指令
 * @param index
 */
const handleRemove = (index) => {
	props.commandList.splice(index, 1)
}
const handleCopy = (index) => {
	const newItem = JSON.parse(JSON.stringify({
		...props.commandList[index], id: generateRandomKey(), lastTime: null
	})); // 深拷贝
	props.commandList.splice(index + 1, 0, newItem)
}

const getLoadBar = computed(() => {
	return (loadBar) => {
		if (loadBar && loadBar instanceof Object) {
			// 代表对象是一个加载条元素
			if (loadBar.id === "loadBar") {
				return loadBar
			} else {
				return null
			}
		}
	}; // 动态参数计算
});

// 拖拽状态
const drag = ref(false)

function onStart() {
	nextTick()
	drag.value = true
}

function onEnd() {
	console.log('onEnd')
	nextTick(() => {
		drag.value = false
	})
}

function handleAdd(item) {
	// 向容器中添加一条空白指令
	let singleCmd = {
		id: generateRandomKey(),
		label: item.label, // 指令名称
		params: item.params,
		deviceName: item.deviceName, // 设备名称
		type: item.type,  // 类型,
		value: void 0, // 指令名称
		exclude_params: item.exclude_params,  // 排除编辑的字段
		remark: void 0,  // 备注
		loadBar: void 0, // 滚动条对象
		relationshipField: [], // 关联遥测
		selected: false, // 是否为当前选中指令
	}
	// 批量操作
	nextTick(() => {
		localCommandList.value.push(singleCmd);
	});
}

const handleLoadingBar = ({loadingBar, index}) => {
	props.commandList[index].loadingBar = loadingBar;
}
// 指令逆向的模态框
const reverseModal = ref(false)
const reverseValue = ref(null)
const targetRef = ref(null)
const reverseList = ref([])
watch(reverseValue, () => {
		// 获取列表,循环构建出最终参数[{hexString:"eb90..", target:obj}]
		const temp = reverseValue.value.match(/eb\s*90\s*.*?\s*09\s*d7/gi) || []
		const result = []
		for (let each of temp) {
			try {
				const buffer = hexStringToUint8Array(each).buffer
				const dv = new DataView(buffer)
				// 第五个字节为指令码
				const commandCode = dv.getUint8(5)
				console.log(dv, commandCode)
				// 从指令配置中找出指令
				const target = commandConfig.optical.instruction_set.find(i => i.params.find(p => parseInt(p.default) === commandCode))
				// 逐个拆解帧,生成帧列表
				const parsedArray = parseArrayBuffer(buffer, target.params.map(p => `${p.type}${p.bit_length}`))
				target.params = target.params.map((p, idx) => {
						console.log(parsedArray[idx])
						return {...p, default: parsedArray[idx]}
					}
				)
				result.push({
					hexString: each,
					target
				})
			} catch
				(e) {
				console.error(e)
			}
		}
		reverseList.value = result
	}
)

/**
 * 加入一条指令到commandList(通过指令逆向)
 */
const addToList = () => {
	reverseList.value.forEach((item) => {
		let temp = {
			id: generateRandomKey(),
			label: item.target.label, // 指令名称
			params: item.target.params, // 指令参数
			deviceName: "光学头", // 设备名称
			type: "warning",  // 类型,
			value: void 0, // 指令名称
			exclude_params: commandConfig.optical.exclude_params,  // 排除编辑的字段
			remark: void 0,  // 备注
			loadBar: void 0, // 滚动条对象
			relationshipField: [], // 关联遥测
			selected: false, // 是否为当前选中指令
		}
		handleAdd(temp)
	})


}
onMounted(() => {
	console.log(props.commandList);
	console.log(deviceList)
	// deviceList.find(device => device.deviceName === item.deviceName).options
})
</script>


<template>
	<!--宽度默认由父元素决定-->
	<section class="h-full bg-zinc-800 rounded flex flex-col overflow-hidden">
		<!--添加指令按钮组-->
		<n-space class="bg-zinc-700/25 rounded mt-1 p-2" size="small" align="center">
			<n-button secondary size="small" @click="reverseModal=!reverseModal">指令逆向</n-button>
			<n-button v-for="item in deviceList"
					  class="h-full"
					  @click="handleAdd(item)"
					  size="small" :type="item.type">
				<template #icon>
					<Add/>
				</template>
				{{ item.deviceName }}
			</n-button>
			<n-text tag="q" depth="3">点击加入一条指令</n-text>
		</n-space>

		<!--指令区域容器-->
		<n-layout-content :native-scrollbar="false"
						  content-class="h-full flex flex-col"
						  class="mt-1 flex justify-between bg-transparent">
			<!--增加可拖拽组件-->
			<VueDraggable
				v-model="localCommandList"
				handle=".handle"
				class="flex flex-col gap-1"
				:scroll="true"
			>
				<!--动画组件-->
				<TransitionGroup
					type="transition"
					:name="!drag ? 'fade' : undefined"
					appear
				>
					<!--需要普通元素包裹才可触发动画-->
					<div v-for="(item, index) in localCommandList" :key="item.id">
						<n-loading-bar-provider
							:to="getLoadBar(item.loadBar)"
							container-style="position: relative;"
							container-class="z-0"
						>
							<!--单条指令组件-->
							<Command
								@loadingBar="handleLoadingBar"
								@removeCmd="_ => handleRemove(index)"
								@copyCmd="_ => handleCopy(index)"
								:cmd-index="index" :cmd-obj="item" :drag="drag"
								:commandOptions="deviceList.find(device => device.deviceName === item.deviceName).options"
							/>

							<!--加载条-->
							<div class="h-0.5"
								 id="loadBar"
								 :ref="(el) => item.loadBar = el"
							/>

						</n-loading-bar-provider>
					</div>
				</TransitionGroup>
			</VueDraggable>
			<n-empty v-if="!commandList || commandList.length <1"
					 class="h-full justify-center">
				没有添加任何指令
			</n-empty>
		</n-layout-content>

		<!--指令逆向弹窗-->
		<n-modal v-model:show="reverseModal">
			<n-card
				class="w-1/2"
				title="指令逆向"
				:bordered="false"
				size="huge"
				role="dialog"
				footer-class="flex"
				aria-modal="true"
				closable
			>
				<template #default>
					<n-text>
						请输入指令源码(支持多条):
					</n-text>
					<n-input type="textarea" placeholder="类似于这样: eb902244..09d7, eb90..09d7"
							 v-model:value="reverseValue"></n-input>
					<n-divider/>
					<n-text>找到了:</n-text>
					<n-flex v-for="(item, index) in reverseList">
						<n-text class="text-wrap flex">

							<n-text>{{ index + 1 }}. {{ item.target.label }}:
								<n-text class="bg-zinc-900 p-1 rounded">{{ item.hexString }}</n-text>
							</n-text>
							<!--							<n-code :word-wrap="true" :code="item.hexString" language="c"></n-code>-->
						</n-text>
					</n-flex>

				</template>
				<template #footer>
					<n-button class="ms-auto" @click="addToList">解析并添加</n-button>
				</template>
			</n-card>
		</n-modal>
	</section>
</template>

<style scoped>
.fade-move,
.fade-enter-active,
.fade-leave-active {
	transition: all 0.5s cubic-bezier(0.55, 0, 0.1, 1);
}

.fade-enter-from,
.fade-leave-to {
	opacity: 0;
	transform: scaleY(0.01) translate(30px, 0);
}

.fade-leave-active {
	position: absolute;
}

.sort-target {
	padding: 0 1rem;
}
</style>